{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "071721f5",
   "metadata": {},
   "source": [
    "## OpenAI函数智能体\n",
    "\n",
    "某些 OpenAI 模型（如 gpt-3.5-turbo-0613 和 gpt-4-0613）已经过微调，可以检测何时应该调用函数，并使用应传递给函数的输入进行响应。在 API 调用中，您可以描述函数，并让模型智能地选择输出包含用于调用这些函数的参数的 JSON 对象。OpenAI 函数 API 的目标是比通用文本补全或聊天 API 更可靠地返回有效和有用的函数调用。\n",
    "\n",
    "许多开源模型都采用了相同的函数调用格式，并且还对模型进行了微调，以检测何时应该调用函数。\n",
    "\n",
    "OpenAI Functions Agent 旨在与这些模型配合使用。\n",
    "\n",
    "安装 openai ， tavily-python 因为 LangChain 软件包在内部调用它们。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "58501ac9",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_openai import ChatOpenAI, OpenAI\n",
    "\n",
    "openai_api_key = \"EMPTY\"\n",
    "openai_api_base = \"http://127.0.0.1:1234/v1\"\n",
    "model = ChatOpenAI(\n",
    "    openai_api_key=openai_api_key,\n",
    "    openai_api_base=openai_api_base,\n",
    "    temperature=0.3,\n",
    ")\n",
    "llm = model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "780ecf9a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "广州\n",
      "广州\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "{'description': '多云', 'temperature': '23'}"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from langchain.tools import BaseTool\n",
    "import requests\n",
    "from typing import Any\n",
    "\n",
    "class Weather(BaseTool):\n",
    "    name = \"weather\"\n",
    "    description = \"根据城市获取天气数据\"\n",
    "    \n",
    "    def __init__(self):\n",
    "        super().__init__()\n",
    "        \n",
    "#     async def _arun(self,*args,**kwargs):\n",
    "#         pass\n",
    "        \n",
    "    def get_weather(self,location):\n",
    "        api_key = \"SKcA5FGgmLvN7faJi\"\n",
    "        url = f\"https://api.seniverse.com/v3/weather/now.json?key={api_key}&location={location}&language=zh-Hans&unit=c\"\n",
    "        response = requests.get(url)\n",
    "        print(location)\n",
    "        if response.status_code == 200:\n",
    "            data = response.json()\n",
    "            #print(data)\n",
    "            weather = {\n",
    "                'description':data['results'][0][\"now\"][\"text\"],\n",
    "                'temperature':data['results'][0][\"now\"][\"temperature\"]\n",
    "            }\n",
    "            return weather\n",
    "        else:\n",
    "            raise Exception(f\"失败接收天气信息：{response.status_code}\")\n",
    "    def _run(self,para):\n",
    "        print(para)\n",
    "        return self.get_weather(para)\n",
    "            \n",
    "weather_tool = Weather()\n",
    "weather_tool.run({\"para\":\"广州\"})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "370eff0a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "ChatPromptTemplate(input_variables=['agent_scratchpad', 'input'], input_types={'chat_history': typing.List[typing.Union[langchain_core.messages.ai.AIMessage, langchain_core.messages.human.HumanMessage, langchain_core.messages.chat.ChatMessage, langchain_core.messages.system.SystemMessage, langchain_core.messages.function.FunctionMessage, langchain_core.messages.tool.ToolMessage]], 'agent_scratchpad': typing.List[typing.Union[langchain_core.messages.ai.AIMessage, langchain_core.messages.human.HumanMessage, langchain_core.messages.chat.ChatMessage, langchain_core.messages.system.SystemMessage, langchain_core.messages.function.FunctionMessage, langchain_core.messages.tool.ToolMessage]]}, messages=[SystemMessagePromptTemplate(prompt=PromptTemplate(input_variables=[], template='You are a helpful assistant')), MessagesPlaceholder(variable_name='chat_history', optional=True), HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=['input'], template='{input}')), MessagesPlaceholder(variable_name='agent_scratchpad')])"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from langchain.agents import AgentExecutor, create_openai_functions_agent\n",
    "from langchain import hub\n",
    "# Get the prompt to use - you can modify this!\n",
    "prompt = hub.pull(\"hwchase17/openai-functions-agent\")\n",
    "prompt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "187b4682",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "RunnableAssign(mapper={\n",
       "  agent_scratchpad: RunnableLambda(lambda x: format_to_openai_function_messages(x['intermediate_steps']))\n",
       "})\n",
       "| ChatPromptTemplate(input_variables=['agent_scratchpad', 'input'], input_types={'chat_history': typing.List[typing.Union[langchain_core.messages.ai.AIMessage, langchain_core.messages.human.HumanMessage, langchain_core.messages.chat.ChatMessage, langchain_core.messages.system.SystemMessage, langchain_core.messages.function.FunctionMessage, langchain_core.messages.tool.ToolMessage]], 'agent_scratchpad': typing.List[typing.Union[langchain_core.messages.ai.AIMessage, langchain_core.messages.human.HumanMessage, langchain_core.messages.chat.ChatMessage, langchain_core.messages.system.SystemMessage, langchain_core.messages.function.FunctionMessage, langchain_core.messages.tool.ToolMessage]]}, messages=[SystemMessagePromptTemplate(prompt=PromptTemplate(input_variables=[], template='You are a helpful assistant')), MessagesPlaceholder(variable_name='chat_history', optional=True), HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=['input'], template='{input}')), MessagesPlaceholder(variable_name='agent_scratchpad')])\n",
       "| RunnableBinding(bound=ChatOpenAI(client=<openai.resources.chat.completions.Completions object at 0x000001BA4FF93790>, async_client=<openai.resources.chat.completions.AsyncCompletions object at 0x000001BA500047C0>, temperature=0.3, openai_api_key=SecretStr('**********'), openai_api_base='http://127.0.0.1:1234/v1', openai_proxy=''), kwargs={'functions': [{'name': 'weather', 'description': '根据城市获取天气数据', 'parameters': {'properties': {'__arg1': {'title': '__arg1', 'type': 'string'}}, 'required': ['__arg1'], 'type': 'object'}}]})\n",
       "| OpenAIFunctionsAgentOutputParser()"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tools = [weather_tool]\n",
    "# Construct the OpenAI Functions agent\n",
    "agent = create_openai_functions_agent(llm, tools, prompt)\n",
    "agent"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "b408aa30",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "AgentExecutor(verbose=True, agent=RunnableAgent(runnable=RunnableAssign(mapper={\n",
       "  agent_scratchpad: RunnableLambda(lambda x: format_to_openai_function_messages(x['intermediate_steps']))\n",
       "})\n",
       "| ChatPromptTemplate(input_variables=['agent_scratchpad', 'input'], input_types={'chat_history': typing.List[typing.Union[langchain_core.messages.ai.AIMessage, langchain_core.messages.human.HumanMessage, langchain_core.messages.chat.ChatMessage, langchain_core.messages.system.SystemMessage, langchain_core.messages.function.FunctionMessage, langchain_core.messages.tool.ToolMessage]], 'agent_scratchpad': typing.List[typing.Union[langchain_core.messages.ai.AIMessage, langchain_core.messages.human.HumanMessage, langchain_core.messages.chat.ChatMessage, langchain_core.messages.system.SystemMessage, langchain_core.messages.function.FunctionMessage, langchain_core.messages.tool.ToolMessage]]}, messages=[SystemMessagePromptTemplate(prompt=PromptTemplate(input_variables=[], template='You are a helpful assistant')), MessagesPlaceholder(variable_name='chat_history', optional=True), HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=['input'], template='{input}')), MessagesPlaceholder(variable_name='agent_scratchpad')])\n",
       "| RunnableBinding(bound=ChatOpenAI(client=<openai.resources.chat.completions.Completions object at 0x000001A5F7692890>, async_client=<openai.resources.chat.completions.AsyncCompletions object at 0x000001A59ACD2560>, temperature=0.3, openai_api_key=SecretStr('**********'), openai_api_base='http://127.0.0.1:1234/v1', openai_proxy=''), kwargs={'functions': [{'name': 'weather', 'description': '根据城市获取天气数据', 'parameters': {'properties': {'__arg1': {'title': '__arg1', 'type': 'string'}}, 'required': ['__arg1'], 'type': 'object'}}]})\n",
       "| OpenAIFunctionsAgentOutputParser(), input_keys_arg=[], return_keys_arg=[]), tools=[Weather()])"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Create an agent executor by passing in the agent and tools\n",
    "agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)\n",
    "agent_executor"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "03fdf233",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3m很抱歉，我无法实时查询最新的天气信息。请访问可靠的天气网站或使用气象应用程序来获取最新、最准确的天气预报。\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "{'input': '今天广州的天气',\n",
       " 'output': '很抱歉，我无法实时查询最新的天气信息。请访问可靠的天气网站或使用气象应用程序来获取最新、最准确的天气预报。'}"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "agent_executor.invoke({\"input\": \"今天广州的天气\"})"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e53752ba",
   "metadata": {},
   "source": [
    "\n",
    "```json\n",
    "{\n",
    "  \"messages\": [\n",
    "    {\n",
    "      \"role\": \"system\",\n",
    "      \"content\": \"You are a helpful assistant\"\n",
    "    },\n",
    "    {\n",
    "      \"role\": \"user\",\n",
    "      \"content\": \"今天广州的天气\"\n",
    "    }\n",
    "  ],\n",
    "  \"model\": \"gpt-3.5-turbo\",\n",
    "  \"functions\": [\n",
    "    {\n",
    "      \"name\": \"weather\",\n",
    "      \"description\": \"根据城市获取天气数据\",\n",
    "      \"parameters\": {\n",
    "        \"properties\": {\n",
    "          \"__arg1\": {\n",
    "            \"title\": \"__arg1\",\n",
    "            \"type\": \"string\"\n",
    "          }\n",
    "        },\n",
    "        \"required\": [\n",
    "          \"__arg1\"\n",
    "        ],\n",
    "        \"type\": \"object\"\n",
    "      }\n",
    "    }\n",
    "  ],\n",
    "  \"n\": 1,\n",
    "  \"stream\": true,\n",
    "  \"temperature\": 0.3\n",
    "}\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "678a7b28",
   "metadata": {},
   "source": [
    "## OpenAI 工具\n",
    "\n",
    "较新的 OpenAI 模型已经过微调，可以检测何时应该调用一个或多个函数，并使用应传递给函数的输入进行响应。在 API 调用中，您可以描述函数，并让模型智能地选择输出包含参数的 JSON 对象来调用这些函数。OpenAI 工具 API 的目标是比使用通用文本补全或聊天 API 更可靠地返回有效和有用的函数调用。\n",
    "\n",
    "OpenAI 将调用单个函数的能力称为函数，将调用一个或多个函数的能力称为工具。\n",
    "\n",
    "在 OpenAI 聊天 API 中，函数现在被视为已弃用的旧选项，取而代之的是工具。\n",
    "\n",
    "如果您使用 OpenAI 模型创建代理，则应使用此 OpenAI 工具代理，而不是 OpenAI 函数代理。\n",
    "\n",
    "使用工具允许模型在适当的时候请求调用多个函数。\n",
    "\n",
    "在某些情况下，这有助于显著减少代理实现其目标所需的时间。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "2af1792e",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_openai import ChatOpenAI, OpenAI\n",
    "\n",
    "openai_api_key = \"EMPTY\"\n",
    "openai_api_base = \"http://127.0.0.1:1234/v1\"\n",
    "model = ChatOpenAI(\n",
    "    openai_api_key=openai_api_key,\n",
    "    openai_api_base=openai_api_base,\n",
    "    temperature=0.3,\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "a9f0eaac",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "ChatPromptTemplate(input_variables=['agent_scratchpad', 'input'], input_types={'chat_history': typing.List[typing.Union[langchain_core.messages.ai.AIMessage, langchain_core.messages.human.HumanMessage, langchain_core.messages.chat.ChatMessage, langchain_core.messages.system.SystemMessage, langchain_core.messages.function.FunctionMessage, langchain_core.messages.tool.ToolMessage]], 'agent_scratchpad': typing.List[typing.Union[langchain_core.messages.ai.AIMessage, langchain_core.messages.human.HumanMessage, langchain_core.messages.chat.ChatMessage, langchain_core.messages.system.SystemMessage, langchain_core.messages.function.FunctionMessage, langchain_core.messages.tool.ToolMessage]]}, messages=[SystemMessagePromptTemplate(prompt=PromptTemplate(input_variables=[], template='You are a helpful assistant')), MessagesPlaceholder(variable_name='chat_history', optional=True), HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=['input'], template='{input}')), MessagesPlaceholder(variable_name='agent_scratchpad')])"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from langchain import hub\n",
    "# Get the prompt to use - you can modify this!\n",
    "prompt = hub.pull(\"hwchase17/openai-tools-agent\")\n",
    "prompt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "1151b093",
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'tools' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "Cell \u001b[1;32mIn[6], line 3\u001b[0m\n\u001b[0;32m      1\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mlangchain\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01magents\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m AgentExecutor, create_openai_tools_agent\n\u001b[0;32m      2\u001b[0m \u001b[38;5;66;03m# Construct the OpenAI Tools agent\u001b[39;00m\n\u001b[1;32m----> 3\u001b[0m agent \u001b[38;5;241m=\u001b[39m create_openai_tools_agent(llm, \u001b[43mtools\u001b[49m, prompt)\n",
      "\u001b[1;31mNameError\u001b[0m: name 'tools' is not defined"
     ]
    }
   ],
   "source": [
    "from langchain.agents import AgentExecutor, create_openai_tools_agent\n",
    "# Construct the OpenAI Tools agent\n",
    "agent = create_openai_tools_agent(llm, tools, prompt)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "bb34f657",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Create an agent executor by passing in the agent and tools\n",
    "agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "6f518c45",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3m很抱歉，我不能实时查询最新的天气情况。请访问可靠的天气网站或使用手机上的天气应用程序来获取最新的广州天气信息。\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "{'input': '今天广州的天气',\n",
       " 'output': '很抱歉，我不能实时查询最新的天气情况。请访问可靠的天气网站或使用手机上的天气应用程序来获取最新的广州天气信息。'}"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "agent_executor.invoke({\"input\": \"今天广州的天气\"})"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "dd2a2240",
   "metadata": {},
   "source": [
    "```json\n",
    "{\n",
    "  \"messages\": [\n",
    "    {\n",
    "      \"role\": \"system\",\n",
    "      \"content\": \"You are a helpful assistant\"\n",
    "    },\n",
    "    {\n",
    "      \"role\": \"user\",\n",
    "      \"content\": \"今天广州的天气\"\n",
    "    }\n",
    "  ],\n",
    "  \"model\": \"gpt-3.5-turbo\",\n",
    "  \"n\": 1,\n",
    "  \"stream\": true,\n",
    "  \"temperature\": 0.3,\n",
    "  \"tools\": [\n",
    "    {\n",
    "      \"type\": \"function\",\n",
    "      \"function\": {\n",
    "        \"name\": \"weather\",\n",
    "        \"description\": \"根据城市获取天气数据\",\n",
    "        \"parameters\": {\n",
    "          \"properties\": {\n",
    "            \"__arg1\": {\n",
    "              \"title\": \"__arg1\",\n",
    "              \"type\": \"string\"\n",
    "            }\n",
    "          },\n",
    "          \"required\": [\n",
    "            \"__arg1\"\n",
    "          ],\n",
    "          \"type\": \"object\"\n",
    "        }\n",
    "      }\n",
    "    }\n",
    "  ]\n",
    "}\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4040de88",
   "metadata": {},
   "source": [
    "## XML 代理\n",
    "\n",
    "一些语言模型（如Anthropic的Claude）特别擅长推理/编写XML。这将介绍如何在提示时使用使用 XML 的代理。\n",
    "\n",
    "仅与非结构化工具一起使用;即接受单个字符串输入的工具。\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "07ff277c",
   "metadata": {},
   "outputs": [],
   "source": [
    "tools = [weather_tool]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "29b617e6",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "ChatPromptTemplate(input_variables=['agent_scratchpad', 'input', 'tools'], partial_variables={'chat_history': ''}, messages=[HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=['agent_scratchpad', 'chat_history', 'input', 'tools'], template=\"You are a helpful assistant. Help the user answer any questions.\\n\\nYou have access to the following tools:\\n\\n{tools}\\n\\nIn order to use a tool, you can use <tool></tool> and <tool_input></tool_input> tags. You will then get back a response in the form <observation></observation>\\nFor example, if you have a tool called 'search' that could run a google search, in order to search for the weather in SF you would respond:\\n\\n<tool>search</tool><tool_input>weather in SF</tool_input>\\n<observation>64 degrees</observation>\\n\\nWhen you are done, respond with a final answer between <final_answer></final_answer>. For example:\\n\\n<final_answer>The weather in SF is 64 degrees</final_answer>\\n\\nBegin!\\n\\nPrevious Conversation:\\n{chat_history}\\n\\nQuestion: {input}\\n{agent_scratchpad}\"))])"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from langchain import hub\n",
    "# Get the prompt to use - you can modify this!\n",
    "prompt = hub.pull(\"hwchase17/xml-agent-convo\")\n",
    "prompt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "e8e3ef6d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "RunnableAssign(mapper={\n",
       "  agent_scratchpad: RunnableLambda(lambda x: format_xml(x['intermediate_steps']))\n",
       "})\n",
       "| ChatPromptTemplate(input_variables=['agent_scratchpad', 'input'], partial_variables={'chat_history': '', 'tools': 'weather: 根据城市获取天气数据'}, messages=[HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=['agent_scratchpad', 'chat_history', 'input', 'tools'], template=\"You are a helpful assistant. Help the user answer any questions.\\n\\nYou have access to the following tools:\\n\\n{tools}\\n\\nIn order to use a tool, you can use <tool></tool> and <tool_input></tool_input> tags. You will then get back a response in the form <observation></observation>\\nFor example, if you have a tool called 'search' that could run a google search, in order to search for the weather in SF you would respond:\\n\\n<tool>search</tool><tool_input>weather in SF</tool_input>\\n<observation>64 degrees</observation>\\n\\nWhen you are done, respond with a final answer between <final_answer></final_answer>. For example:\\n\\n<final_answer>The weather in SF is 64 degrees</final_answer>\\n\\nBegin!\\n\\nPrevious Conversation:\\n{chat_history}\\n\\nQuestion: {input}\\n{agent_scratchpad}\"))])\n",
       "| RunnableBinding(bound=ChatOpenAI(client=<openai.resources.chat.completions.Completions object at 0x000001BA4FF93790>, async_client=<openai.resources.chat.completions.AsyncCompletions object at 0x000001BA500047C0>, temperature=0.3, openai_api_key=SecretStr('**********'), openai_api_base='http://127.0.0.1:1234/v1', openai_proxy=''), kwargs={'stop': ['</tool_input>']})\n",
       "| XMLAgentOutputParser()"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from langchain.agents import AgentExecutor, create_xml_agent\n",
    "\n",
    "# Choose the LLM that will drive the agent\n",
    "llm = model\n",
    "\n",
    "# Construct the XML agent\n",
    "agent = create_xml_agent(llm, tools, prompt)\n",
    "agent"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "31f99d30",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Create an agent executor by passing in the agent and tools\n",
    "agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "6f96639f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3m<tool>weather</tool><tool_input>广州\u001b[0m广州\n",
      "广州\n",
      "\u001b[36;1m\u001b[1;3m{'description': '阴', 'temperature': '21'}\u001b[0m\u001b[32;1m\u001b[1;3m<final_answer>今天的广州天气是阴，温度为21度。</final_answer>\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "{'input': '今天广州的天气', 'output': '今天的广州天气是阴，温度为21度。'}"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "agent_executor.invoke({\"input\": \"今天广州的天气\"})"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7fc1fb36",
   "metadata": {},
   "source": [
    "You are a helpful assistant. Help the user answer any questions.\\n\\nYou have access to the following tools:\\n\\nweather: 根据城市获取天气数据\\n\\nIn order to use a tool, you can use <tool></tool> and <tool_input></tool_input> tags. You will then get back a response in the form <observation></observation>\\nFor example, if you have a tool called 'search' that could run a google search, in order to search for the weather in SF you would respond:\\n\\n<tool>search</tool><tool_input>weather in SF</tool_input>\\n<observation>64 degrees</observation>\\n\\nWhen you are done, respond with a final answer between <final_answer></final_answer>. For example:\\n\\n<final_answer>The weather in SF is 64 degrees</final_answer>\\n\\nBegin!\\n\\nPrevious Conversation:\\n\\n\\nQuestion: 今天广州的天气\\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4cdd9e51",
   "metadata": {},
   "source": [
    "You are a helpful assistant. Help the user answer any questions.\\n\\nYou have access to the following tools:\\n\\nweather: 根据城市获取天气数据\\n\\nIn order to use a tool, you can use <tool></tool> and <tool_input></tool_input> tags. You will then get back a response in the form <observation></observation>\\nFor example, if you have a tool called 'search' that could run a google search, in order to search for the weather in SF you would respond:\\n\\n<tool>search</tool><tool_input>weather in SF</tool_input>\\n<observation>64 degrees</observation>\\n\\nWhen you are done, respond with a final answer between <final_answer></final_answer>. For example:\\n\\n<final_answer>The weather in SF is 64 degrees</final_answer>\\n\\nBegin!\\n\\nPrevious Conversation:\\n\\n\\nQuestion: 今天广州的天气\\n<tool>weather</tool><tool_input>广州</tool_input><observation>{'description': '阴', 'temperature': '21'}</observation>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "94166144",
   "metadata": {},
   "source": [
    "## JSON 聊天代理\n",
    "\n",
    "一些语言模型特别擅长编写 JSON。此代理使用 JSON 来格式化其输出，旨在支持聊天模型。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "c53cf11c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "ChatPromptTemplate(input_variables=['agent_scratchpad', 'input', 'tool_names', 'tools'], input_types={'chat_history': typing.List[typing.Union[langchain_core.messages.ai.AIMessage, langchain_core.messages.human.HumanMessage, langchain_core.messages.chat.ChatMessage, langchain_core.messages.system.SystemMessage, langchain_core.messages.function.FunctionMessage, langchain_core.messages.tool.ToolMessage]], 'agent_scratchpad': typing.List[typing.Union[langchain_core.messages.ai.AIMessage, langchain_core.messages.human.HumanMessage, langchain_core.messages.chat.ChatMessage, langchain_core.messages.system.SystemMessage, langchain_core.messages.function.FunctionMessage, langchain_core.messages.tool.ToolMessage]]}, messages=[SystemMessagePromptTemplate(prompt=PromptTemplate(input_variables=[], template='Assistant is a large language model trained by OpenAI.\\n\\nAssistant is designed to be able to assist with a wide range of tasks, from answering simple questions to providing in-depth explanations and discussions on a wide range of topics. As a language model, Assistant is able to generate human-like text based on the input it receives, allowing it to engage in natural-sounding conversations and provide responses that are coherent and relevant to the topic at hand.\\n\\nAssistant is constantly learning and improving, and its capabilities are constantly evolving. It is able to process and understand large amounts of text, and can use this knowledge to provide accurate and informative responses to a wide range of questions. Additionally, Assistant is able to generate its own text based on the input it receives, allowing it to engage in discussions and provide explanations and descriptions on a wide range of topics.\\n\\nOverall, Assistant is a powerful system that can help with a wide range of tasks and provide valuable insights and information on a wide range of topics. Whether you need help with a specific question or just want to have a conversation about a particular topic, Assistant is here to assist.')), MessagesPlaceholder(variable_name='chat_history', optional=True), HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=['input', 'tool_names', 'tools'], template='TOOLS\\n------\\nAssistant can ask the user to use tools to look up information that may be helpful in answering the users original question. The tools the human can use are:\\n\\n{tools}\\n\\nRESPONSE FORMAT INSTRUCTIONS\\n----------------------------\\n\\nWhen responding to me, please output a response in one of two formats:\\n\\n**Option 1:**\\nUse this if you want the human to use a tool.\\nMarkdown code snippet formatted in the following schema:\\n\\n```json\\n{{\\n    \"action\": string, \\\\ The action to take. Must be one of {tool_names}\\n    \"action_input\": string \\\\ The input to the action\\n}}\\n```\\n\\n**Option #2:**\\nUse this if you want to respond directly to the human. Markdown code snippet formatted in the following schema:\\n\\n```json\\n{{\\n    \"action\": \"Final Answer\",\\n    \"action_input\": string \\\\ You should put what you want to return to use here\\n}}\\n```\\n\\nUSER\\'S INPUT\\n--------------------\\nHere is the user\\'s input (remember to respond with a markdown code snippet of a json blob with a single action, and NOTHING else):\\n\\n{input}')), MessagesPlaceholder(variable_name='agent_scratchpad')])"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from langchain.agents import AgentExecutor, create_json_chat_agent\n",
    "\n",
    "# Get the prompt to use - you can modify this!\n",
    "prompt = hub.pull(\"hwchase17/react-chat-json\")\n",
    "prompt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "1e8071c4",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "RunnableAssign(mapper={\n",
       "  agent_scratchpad: RunnableLambda(lambda x: format_log_to_messages(x['intermediate_steps'], template_tool_response=TEMPLATE_TOOL_RESPONSE))\n",
       "})\n",
       "| ChatPromptTemplate(input_variables=['agent_scratchpad', 'input'], input_types={'chat_history': typing.List[typing.Union[langchain_core.messages.ai.AIMessage, langchain_core.messages.human.HumanMessage, langchain_core.messages.chat.ChatMessage, langchain_core.messages.system.SystemMessage, langchain_core.messages.function.FunctionMessage, langchain_core.messages.tool.ToolMessage]], 'agent_scratchpad': typing.List[typing.Union[langchain_core.messages.ai.AIMessage, langchain_core.messages.human.HumanMessage, langchain_core.messages.chat.ChatMessage, langchain_core.messages.system.SystemMessage, langchain_core.messages.function.FunctionMessage, langchain_core.messages.tool.ToolMessage]]}, partial_variables={'tools': 'weather: 根据城市获取天气数据', 'tool_names': 'weather'}, messages=[SystemMessagePromptTemplate(prompt=PromptTemplate(input_variables=[], template='Assistant is a large language model trained by OpenAI.\\n\\nAssistant is designed to be able to assist with a wide range of tasks, from answering simple questions to providing in-depth explanations and discussions on a wide range of topics. As a language model, Assistant is able to generate human-like text based on the input it receives, allowing it to engage in natural-sounding conversations and provide responses that are coherent and relevant to the topic at hand.\\n\\nAssistant is constantly learning and improving, and its capabilities are constantly evolving. It is able to process and understand large amounts of text, and can use this knowledge to provide accurate and informative responses to a wide range of questions. Additionally, Assistant is able to generate its own text based on the input it receives, allowing it to engage in discussions and provide explanations and descriptions on a wide range of topics.\\n\\nOverall, Assistant is a powerful system that can help with a wide range of tasks and provide valuable insights and information on a wide range of topics. Whether you need help with a specific question or just want to have a conversation about a particular topic, Assistant is here to assist.')), MessagesPlaceholder(variable_name='chat_history', optional=True), HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=['input', 'tool_names', 'tools'], template='TOOLS\\n------\\nAssistant can ask the user to use tools to look up information that may be helpful in answering the users original question. The tools the human can use are:\\n\\n{tools}\\n\\nRESPONSE FORMAT INSTRUCTIONS\\n----------------------------\\n\\nWhen responding to me, please output a response in one of two formats:\\n\\n**Option 1:**\\nUse this if you want the human to use a tool.\\nMarkdown code snippet formatted in the following schema:\\n\\n```json\\n{{\\n    \"action\": string, \\\\ The action to take. Must be one of {tool_names}\\n    \"action_input\": string \\\\ The input to the action\\n}}\\n```\\n\\n**Option #2:**\\nUse this if you want to respond directly to the human. Markdown code snippet formatted in the following schema:\\n\\n```json\\n{{\\n    \"action\": \"Final Answer\",\\n    \"action_input\": string \\\\ You should put what you want to return to use here\\n}}\\n```\\n\\nUSER\\'S INPUT\\n--------------------\\nHere is the user\\'s input (remember to respond with a markdown code snippet of a json blob with a single action, and NOTHING else):\\n\\n{input}')), MessagesPlaceholder(variable_name='agent_scratchpad')])\n",
       "| RunnableBinding(bound=ChatOpenAI(client=<openai.resources.chat.completions.Completions object at 0x00000232AD247430>, async_client=<openai.resources.chat.completions.AsyncCompletions object at 0x00000232AD2B4460>, temperature=0.3, openai_api_key=SecretStr('**********'), openai_api_base='http://127.0.0.1:1234/v1', openai_proxy=''), kwargs={'stop': ['\\nObservation']})\n",
       "| JSONAgentOutputParser()"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Construct the JSON agent\n",
    "agent = create_json_chat_agent(llm, tools, prompt)\n",
    "agent"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "6c5e2cf9",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Create an agent executor by passing in the agent and tools\n",
    "agent_executor = AgentExecutor(\n",
    "    agent=agent, tools=tools, verbose=True, handle_parsing_errors=True\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "3c5b3ca7",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3m```json\n",
      "{\n",
      "    \"action\": \"weather\",\n",
      "    \"action_input\": \"广州\"\n",
      "}\n",
      "```\u001b[0m广州\n",
      "广州\n",
      "\u001b[36;1m\u001b[1;3m{'description': '阴', 'temperature': '20'}\u001b[0m\u001b[32;1m\u001b[1;3m```json\n",
      "{\n",
      "    \"action\": \"Final Answer\",\n",
      "    \"action_input\": \"今天广州的天气是阴天，气温为20度。\"\n",
      "}\n",
      "```\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "{'input': '今天广州的天气', 'output': '今天广州的天气是阴天，气温为20度。'}"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "agent_executor.invoke({\"input\": \"今天广州的天气\"})"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "08ec6b36",
   "metadata": {},
   "source": [
    "```json\n",
    "{\n",
    "  \"messages\": [\n",
    "    {\n",
    "      \"role\": \"system\",\n",
    "      \"content\": \"Assistant is a large language model trained by OpenAI.\\n\\nAssistant is designed to be able to assist with a wide range of tasks, from answering simple questions to providing in-depth explanations and discussions on a wide range of topics. As a language model, Assistant is able to generate human-like text based on the input it receives, allowing it to engage in natural-sounding conversations and provide responses that are coherent and relevant to the topic at hand.\\n\\nAssistant is constantly learning and improving, and its capabilities are constantly evolving. It is able to process and understand large amounts of text, and can use this knowledge to provide accurate and informative responses to a wide range of questions. Additionally, Assistant is able to generate its own text based on the input it receives, allowing it to engage in discussions and provide explanations and descriptions on a wide range of topics.\\n\\nOverall, Assistant is a powerful system that can help with a wide range of tasks and provide valuable insights and information on a wide range of topics. Whether you need help with a specific question or just want to have a conversation about a particular topic, Assistant is here to assist.\"\n",
    "    },\n",
    "    {\n",
    "      \"role\": \"user\",\n",
    "      \"content\": \"TOOLS\\n------\\nAssistant can ask the user to use tools to look up information that may be helpful in answering the users original question. The tools the human can use are:\\n\\nweather: 根据城市获取天气数据\\n\\nRESPONSE FORMAT INSTRUCTIONS\\n----------------------------\\n\\nWhen responding to me, please output a response in one of two formats:\\n\\n**Option 1:**\\nUse this if you want the human to use a tool.\\nMarkdown code snippet formatted in the following schema:\\n\\n```json\\n{\\n    \\\"action\\\": string, \\\\ The action to take. Must be one of weather\\n    \\\"action_input\\\": string \\\\ The input to the action\\n}\\n```\\n\\n**Option #2:**\\nUse this if you want to respond directly to the human. Markdown code snippet formatted in the following schema:\\n\\n```json\\n{\\n    \\\"action\\\": \\\"Final Answer\\\",\\n    \\\"action_input\\\": string \\\\ You should put what you want to return to use here\\n}\\n```\\n\\nUSER'S INPUT\\n--------------------\\nHere is the user's input (remember to respond with a markdown code snippet of a json blob with a single action, and NOTHING else):\\n\\n今天广州的天气\"\n",
    "    }\n",
    "  ],\n",
    "  \"model\": \"gpt-3.5-turbo\",\n",
    "  \"n\": 1,\n",
    "  \"stop\": [\n",
    "    \"\\nObservation\"\n",
    "  ],\n",
    "  \"stream\": true,\n",
    "  \"temperature\": 0.3\n",
    "}\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e81eeb21",
   "metadata": {},
   "source": [
    "```python\n",
    "\n",
    "{\n",
    "  \"messages\": [\n",
    "    {\n",
    "      \"role\": \"system\",\n",
    "      \"content\": \"Assistant is a large language model trained by OpenAI.\\n\\nAssistant is designed to be able to assist with a wide range of tasks, from answering simple questions to providing in-depth explanations and discussions on a wide range of topics. As a language model, Assistant is able to generate human-like text based on the input it receives, allowing it to engage in natural-sounding conversations and provide responses that are coherent and relevant to the topic at hand.\\n\\nAssistant is constantly learning and improving, and its capabilities are constantly evolving. It is able to process and understand large amounts of text, and can use this knowledge to provide accurate and informative responses to a wide range of questions. Additionally, Assistant is able to generate its own text based on the input it receives, allowing it to engage in discussions and provide explanations and descriptions on a wide range of topics.\\n\\nOverall, Assistant is a powerful system that can help with a wide range of tasks and provide valuable insights and information on a wide range of topics. Whether you need help with a specific question or just want to have a conversation about a particular topic, Assistant is here to assist.\"\n",
    "    },\n",
    "    {\n",
    "      \"role\": \"user\",\n",
    "      \"content\": \"TOOLS\\n------\\nAssistant can ask the user to use tools to look up information that may be helpful in answering the users original question. The tools the human can use are:\\n\\nweather: 根据城市获取天气数据\\n\\nRESPONSE FORMAT INSTRUCTIONS\\n----------------------------\\n\\nWhen responding to me, please output a response in one of two formats:\\n\\n**Option 1:**\\nUse this if you want the human to use a tool.\\nMarkdown code snippet formatted in the following schema:\\n\\n```json\\n{\\n    \\\"action\\\": string, \\\\ The action to take. Must be one of weather\\n    \\\"action_input\\\": string \\\\ The input to the action\\n}\\n```\\n\\n**Option #2:**\\nUse this if you want to respond directly to the human. Markdown code snippet formatted in the following schema:\\n\\n```json\\n{\\n    \\\"action\\\": \\\"Final Answer\\\",\\n    \\\"action_input\\\": string \\\\ You should put what you want to return to use here\\n}\\n```\\n\\nUSER'S INPUT\\n--------------------\\nHere is the user's input (remember to respond with a markdown code snippet of a json blob with a single action, and NOTHING else):\\n\\n今天广州的天气\"\n",
    "    },\n",
    "    {\n",
    "      \"role\": \"assistant\",\n",
    "      \"content\": \"```json\\n{\\n    \\\"action\\\": \\\"weather\\\",\\n    \\\"action_input\\\": \\\"广州\\\"\\n}\\n```\"\n",
    "    },\n",
    "    {\n",
    "      \"role\": \"user\",\n",
    "      \"content\": \"TOOL RESPONSE: \\n---------------------\\n{'description': '阴', 'temperature': '20'}\\n\\nUSER'S INPUT\\n--------------------\\n\\nOkay, so what is the response to my last comment? If using information obtained from the tools you must mention it explicitly without mentioning the tool names - I have forgotten all TOOL RESPONSES! Remember to respond with a markdown code snippet of a json blob with a single action, and NOTHING else - even if you just want to respond to the user. Do NOT respond with anything except a JSON snippet no matter what!\"\n",
    "    }\n",
    "  ],\n",
    "  \"model\": \"gpt-3.5-turbo\",\n",
    "  \"n\": 1,\n",
    "  \"stop\": [\n",
    "    \"\\nObservation\"\n",
    "  ],\n",
    "  \"stream\": true,\n",
    "  \"temperature\": 0.3\n",
    "}\n",
    "\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9c93234c",
   "metadata": {},
   "source": [
    "## ReAct Agent\n",
    "\n",
    "\n",
    "ReAct(reason, act)整合了推理和行动能力，是一种使用自然语言推理解决复杂任务的语言模型。ReAct旨在用于允许LLM执行某些操作的任务。例如，在MRKL系统中，LLM可以与外部API交互以检索信息。当提出问题时，LLM可以选择执行操作以检索信息，然后根据检索到的信息回答问题。\n",
    "\n",
    "ReAct系统可以被视为具有推理和行动能力的MRKL系统。\n",
    "给机器人小明一个任务：去厨房为你做一杯咖啡。小明不仅要完成这个任务，还要告诉你他是如何一步步完成的。\n",
    "\n",
    "### 缺乏ReAct的机器人系统：\n",
    "\n",
    "1. 小明直接跑到厨房。\n",
    "2. 你听到了一些声音，但不知道小明在做什么。\n",
    "3. 过了一会儿，小明回来给你一杯咖啡。\n",
    "4. 这样的问题是，你不知道小明是怎么做咖啡的，他是否加了糖或奶，或者他是否在过程中遇到了任何问题。\n",
    "\n",
    "### ReAct的机器人系统：\n",
    "\n",
    "    - Thought 1：“我现在去厨房。”\n",
    "    - Act 1：“启动进入厨房。”\n",
    "    - Obs 1：“看到厨房内的环境。”\n",
    "\n",
    "\n",
    "    - Thought 2：“我需要找到咖啡粉和咖啡机。”\n",
    "    - Act 2：“寻找咖啡粉和咖啡机。”\n",
    "    - Obs 2：“找到了咖啡粉和咖啡机。”\n",
    "\n",
    "\n",
    "    - Thought 3：“我现在可以开始煮咖啡了。”\n",
    "    - Act 3：“开始煮咖啡。”\n",
    "    - Obs 3：“咖啡做好了。”\n",
    "\n",
    "\n",
    "    - Thought 4：“可以把咖啡送过去了。”\n",
    "    - Act 4：“送咖啡。”\n",
    "    - Obs 4：“得到了表扬。”\n",
    "\n",
    "ReAct能够首先通过推理问题（Thought 1），然后执行一个动作（Act 1）。然后它收到了一个观察（Obs 1），并继续进行这个思想，行动，观察循环，直到达到结论。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "id": "3af578a0",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "PromptTemplate(input_variables=['agent_scratchpad', 'input', 'tool_names', 'tools'], template='Answer the following questions as best you can. You have access to the following tools:\\n\\n{tools}\\n\\nUse the following format:\\n\\nQuestion: the input question you must answer\\nThought: you should always think about what to do\\nAction: the action to take, should be one of [{tool_names}]\\nAction Input: the input to the action\\nObservation: the result of the action\\n... (this Thought/Action/Action Input/Observation can repeat N times)\\nThought: I now know the final answer\\nFinal Answer: the final answer to the original input question\\n\\nBegin!\\n\\nQuestion: {input}\\nThought:{agent_scratchpad}')"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from langchain.agents import AgentExecutor, create_react_agent\n",
    "\n",
    "# Get the prompt to use - you can modify this!\n",
    "prompt = hub.pull(\"hwchase17/react\")\n",
    "prompt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "id": "6b41dac0",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "RunnableAssign(mapper={\n",
       "  agent_scratchpad: RunnableLambda(lambda x: format_log_to_str(x['intermediate_steps']))\n",
       "})\n",
       "| PromptTemplate(input_variables=['agent_scratchpad', 'input'], partial_variables={'tools': 'weather: 根据城市获取天气数据', 'tool_names': 'weather'}, template='Answer the following questions as best you can. You have access to the following tools:\\n\\n{tools}\\n\\nUse the following format:\\n\\nQuestion: the input question you must answer\\nThought: you should always think about what to do\\nAction: the action to take, should be one of [{tool_names}]\\nAction Input: the input to the action\\nObservation: the result of the action\\n... (this Thought/Action/Action Input/Observation can repeat N times)\\nThought: I now know the final answer\\nFinal Answer: the final answer to the original input question\\n\\nBegin!\\n\\nQuestion: {input}\\nThought:{agent_scratchpad}')\n",
       "| RunnableBinding(bound=ChatOpenAI(client=<openai.resources.chat.completions.Completions object at 0x00000232AD247430>, async_client=<openai.resources.chat.completions.AsyncCompletions object at 0x00000232AD2B4460>, temperature=0.3, openai_api_key=SecretStr('**********'), openai_api_base='http://127.0.0.1:1234/v1', openai_proxy=''), kwargs={'stop': ['\\nObservation']})\n",
       "| ReActSingleInputOutputParser()"
      ]
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Construct the ReAct agent\n",
    "agent = create_react_agent(llm, tools, prompt)\n",
    "agent"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "id": "8ca8fa09",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "AgentExecutor(verbose=True, agent=RunnableAgent(runnable=RunnableAssign(mapper={\n",
       "  agent_scratchpad: RunnableLambda(lambda x: format_log_to_str(x['intermediate_steps']))\n",
       "})\n",
       "| PromptTemplate(input_variables=['agent_scratchpad', 'input'], partial_variables={'tools': 'weather: 根据城市获取天气数据', 'tool_names': 'weather'}, template='Answer the following questions as best you can. You have access to the following tools:\\n\\n{tools}\\n\\nUse the following format:\\n\\nQuestion: the input question you must answer\\nThought: you should always think about what to do\\nAction: the action to take, should be one of [{tool_names}]\\nAction Input: the input to the action\\nObservation: the result of the action\\n... (this Thought/Action/Action Input/Observation can repeat N times)\\nThought: I now know the final answer\\nFinal Answer: the final answer to the original input question\\n\\nBegin!\\n\\nQuestion: {input}\\nThought:{agent_scratchpad}')\n",
       "| RunnableBinding(bound=ChatOpenAI(client=<openai.resources.chat.completions.Completions object at 0x00000232AD247430>, async_client=<openai.resources.chat.completions.AsyncCompletions object at 0x00000232AD2B4460>, temperature=0.3, openai_api_key=SecretStr('**********'), openai_api_base='http://127.0.0.1:1234/v1', openai_proxy=''), kwargs={'stop': ['\\nObservation']})\n",
       "| ReActSingleInputOutputParser(), input_keys_arg=[], return_keys_arg=[]), tools=[Weather()])"
      ]
     },
     "execution_count": 35,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Create an agent executor by passing in the agent and tools\n",
    "agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)\n",
    "agent_executor"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "id": "7df5918b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3mThought: I need to find out the weather in Guangzhou today.\n",
      "Action: [weather]\n",
      "Action Input: \"Guangzhou\", \"today\"\u001b[0m[weather] is not a valid tool, try one of [weather].\u001b[32;1m\u001b[1;3mI apologize for the confusion earlier. Here's the correct response to your question:\n",
      "\n",
      "Question: 今天广州的天气\n",
      "Thought: I need to find out the weather in Guangzhou today.\n",
      "Action: [weather]\n",
      "Action Input: \"Guangzhou\", \"today\"\u001b[0m[weather] is not a valid tool, try one of [weather].\u001b[32;1m\u001b[1;3mI apologize for the confusion earlier. Here's the correct response to your question:\n",
      "\n",
      "Question: 今天广州的天气\n",
      "Thought: I need to find out the weather in Guangzhou today.\n",
      "Action: [weather]\n",
      "Action Input: \"Guangzhou\", \"today\"\u001b[0m[weather] is not a valid tool, try one of [weather]."
     ]
    },
    {
     "ename": "ValueError",
     "evalue": "An output parsing error occurred. In order to pass this error back to the agent and have it try again, pass `handle_parsing_errors=True` to the AgentExecutor. This is the error: Could not parse LLM output: `I apologize for the confusion earlier. Here's the correct response to your question:`",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mOutputParserException\u001b[0m                     Traceback (most recent call last)",
      "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python310\\site-packages\\langchain\\agents\\agent.py:1125\u001b[0m, in \u001b[0;36mAgentExecutor._iter_next_step\u001b[1;34m(self, name_to_tool_map, color_mapping, inputs, intermediate_steps, run_manager)\u001b[0m\n\u001b[0;32m   1124\u001b[0m     \u001b[38;5;66;03m# Call the LLM to see what to do.\u001b[39;00m\n\u001b[1;32m-> 1125\u001b[0m     output \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39magent\u001b[38;5;241m.\u001b[39mplan(\n\u001b[0;32m   1126\u001b[0m         intermediate_steps,\n\u001b[0;32m   1127\u001b[0m         callbacks\u001b[38;5;241m=\u001b[39mrun_manager\u001b[38;5;241m.\u001b[39mget_child() \u001b[38;5;28;01mif\u001b[39;00m run_manager \u001b[38;5;28;01melse\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m,\n\u001b[0;32m   1128\u001b[0m         \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39minputs,\n\u001b[0;32m   1129\u001b[0m     )\n\u001b[0;32m   1130\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m OutputParserException \u001b[38;5;28;01mas\u001b[39;00m e:\n",
      "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python310\\site-packages\\langchain\\agents\\agent.py:387\u001b[0m, in \u001b[0;36mRunnableAgent.plan\u001b[1;34m(self, intermediate_steps, callbacks, **kwargs)\u001b[0m\n\u001b[0;32m    386\u001b[0m final_output: Any \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[1;32m--> 387\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m chunk \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mrunnable\u001b[38;5;241m.\u001b[39mstream(inputs, config\u001b[38;5;241m=\u001b[39m{\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mcallbacks\u001b[39m\u001b[38;5;124m\"\u001b[39m: callbacks}):\n\u001b[0;32m    388\u001b[0m     \u001b[38;5;28;01mif\u001b[39;00m final_output \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n",
      "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python310\\site-packages\\langchain_core\\runnables\\base.py:2446\u001b[0m, in \u001b[0;36mRunnableSequence.stream\u001b[1;34m(self, input, config, **kwargs)\u001b[0m\n\u001b[0;32m   2440\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mstream\u001b[39m(\n\u001b[0;32m   2441\u001b[0m     \u001b[38;5;28mself\u001b[39m,\n\u001b[0;32m   2442\u001b[0m     \u001b[38;5;28minput\u001b[39m: Input,\n\u001b[0;32m   2443\u001b[0m     config: Optional[RunnableConfig] \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m,\n\u001b[0;32m   2444\u001b[0m     \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs: Optional[Any],\n\u001b[0;32m   2445\u001b[0m ) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m Iterator[Output]:\n\u001b[1;32m-> 2446\u001b[0m     \u001b[38;5;28;01myield from\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mtransform(\u001b[38;5;28miter\u001b[39m([\u001b[38;5;28minput\u001b[39m]), config, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n",
      "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python310\\site-packages\\langchain_core\\runnables\\base.py:2433\u001b[0m, in \u001b[0;36mRunnableSequence.transform\u001b[1;34m(self, input, config, **kwargs)\u001b[0m\n\u001b[0;32m   2427\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mtransform\u001b[39m(\n\u001b[0;32m   2428\u001b[0m     \u001b[38;5;28mself\u001b[39m,\n\u001b[0;32m   2429\u001b[0m     \u001b[38;5;28minput\u001b[39m: Iterator[Input],\n\u001b[0;32m   2430\u001b[0m     config: Optional[RunnableConfig] \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m,\n\u001b[0;32m   2431\u001b[0m     \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs: Optional[Any],\n\u001b[0;32m   2432\u001b[0m ) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m Iterator[Output]:\n\u001b[1;32m-> 2433\u001b[0m     \u001b[38;5;28;01myield from\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_transform_stream_with_config(\n\u001b[0;32m   2434\u001b[0m         \u001b[38;5;28minput\u001b[39m,\n\u001b[0;32m   2435\u001b[0m         \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_transform,\n\u001b[0;32m   2436\u001b[0m         patch_config(config, run_name\u001b[38;5;241m=\u001b[39m(config \u001b[38;5;129;01mor\u001b[39;00m {})\u001b[38;5;241m.\u001b[39mget(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mrun_name\u001b[39m\u001b[38;5;124m\"\u001b[39m) \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mname),\n\u001b[0;32m   2437\u001b[0m         \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs,\n\u001b[0;32m   2438\u001b[0m     )\n",
      "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python310\\site-packages\\langchain_core\\runnables\\base.py:1513\u001b[0m, in \u001b[0;36mRunnable._transform_stream_with_config\u001b[1;34m(self, input, transformer, config, run_type, **kwargs)\u001b[0m\n\u001b[0;32m   1512\u001b[0m \u001b[38;5;28;01mwhile\u001b[39;00m \u001b[38;5;28;01mTrue\u001b[39;00m:\n\u001b[1;32m-> 1513\u001b[0m     chunk: Output \u001b[38;5;241m=\u001b[39m \u001b[43mcontext\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrun\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mnext\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43miterator\u001b[49m\u001b[43m)\u001b[49m  \u001b[38;5;66;03m# type: ignore\u001b[39;00m\n\u001b[0;32m   1514\u001b[0m     \u001b[38;5;28;01myield\u001b[39;00m chunk\n",
      "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python310\\site-packages\\langchain_core\\runnables\\base.py:2397\u001b[0m, in \u001b[0;36mRunnableSequence._transform\u001b[1;34m(self, input, run_manager, config)\u001b[0m\n\u001b[0;32m   2389\u001b[0m     final_pipeline \u001b[38;5;241m=\u001b[39m step\u001b[38;5;241m.\u001b[39mtransform(\n\u001b[0;32m   2390\u001b[0m         final_pipeline,\n\u001b[0;32m   2391\u001b[0m         patch_config(\n\u001b[1;32m   (...)\u001b[0m\n\u001b[0;32m   2394\u001b[0m         ),\n\u001b[0;32m   2395\u001b[0m     )\n\u001b[1;32m-> 2397\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m output \u001b[38;5;129;01min\u001b[39;00m final_pipeline:\n\u001b[0;32m   2398\u001b[0m     \u001b[38;5;28;01myield\u001b[39;00m output\n",
      "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python310\\site-packages\\langchain_core\\runnables\\base.py:1061\u001b[0m, in \u001b[0;36mRunnable.transform\u001b[1;34m(self, input, config, **kwargs)\u001b[0m\n\u001b[0;32m   1060\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m got_first_val:\n\u001b[1;32m-> 1061\u001b[0m     \u001b[38;5;28;01myield from\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mstream(final, config, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n",
      "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python310\\site-packages\\langchain_core\\runnables\\base.py:577\u001b[0m, in \u001b[0;36mRunnable.stream\u001b[1;34m(self, input, config, **kwargs)\u001b[0m\n\u001b[0;32m    573\u001b[0m \u001b[38;5;250m\u001b[39m\u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[0;32m    574\u001b[0m \u001b[38;5;124;03mDefault implementation of stream, which calls invoke.\u001b[39;00m\n\u001b[0;32m    575\u001b[0m \u001b[38;5;124;03mSubclasses should override this method if they support streaming output.\u001b[39;00m\n\u001b[0;32m    576\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m--> 577\u001b[0m \u001b[38;5;28;01myield\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39minvoke(\u001b[38;5;28minput\u001b[39m, config, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n",
      "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python310\\site-packages\\langchain_core\\output_parsers\\base.py:169\u001b[0m, in \u001b[0;36mBaseOutputParser.invoke\u001b[1;34m(self, input, config)\u001b[0m\n\u001b[0;32m    168\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(\u001b[38;5;28minput\u001b[39m, BaseMessage):\n\u001b[1;32m--> 169\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_call_with_config\u001b[49m\u001b[43m(\u001b[49m\n\u001b[0;32m    170\u001b[0m \u001b[43m        \u001b[49m\u001b[38;5;28;43;01mlambda\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43minner_input\u001b[49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mparse_result\u001b[49m\u001b[43m(\u001b[49m\n\u001b[0;32m    171\u001b[0m \u001b[43m            \u001b[49m\u001b[43m[\u001b[49m\u001b[43mChatGeneration\u001b[49m\u001b[43m(\u001b[49m\u001b[43mmessage\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43minner_input\u001b[49m\u001b[43m)\u001b[49m\u001b[43m]\u001b[49m\n\u001b[0;32m    172\u001b[0m \u001b[43m        \u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    173\u001b[0m \u001b[43m        \u001b[49m\u001b[38;5;28;43minput\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[0;32m    174\u001b[0m \u001b[43m        \u001b[49m\u001b[43mconfig\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    175\u001b[0m \u001b[43m        \u001b[49m\u001b[43mrun_type\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mparser\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[0;32m    176\u001b[0m \u001b[43m    \u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m    177\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n",
      "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python310\\site-packages\\langchain_core\\runnables\\base.py:1262\u001b[0m, in \u001b[0;36mRunnable._call_with_config\u001b[1;34m(self, func, input, config, run_type, **kwargs)\u001b[0m\n\u001b[0;32m   1259\u001b[0m     context\u001b[38;5;241m.\u001b[39mrun(var_child_runnable_config\u001b[38;5;241m.\u001b[39mset, child_config)\n\u001b[0;32m   1260\u001b[0m     output \u001b[38;5;241m=\u001b[39m cast(\n\u001b[0;32m   1261\u001b[0m         Output,\n\u001b[1;32m-> 1262\u001b[0m         context\u001b[38;5;241m.\u001b[39mrun(\n\u001b[0;32m   1263\u001b[0m             call_func_with_variable_args,\n\u001b[0;32m   1264\u001b[0m             func,  \u001b[38;5;66;03m# type: ignore[arg-type]\u001b[39;00m\n\u001b[0;32m   1265\u001b[0m             \u001b[38;5;28minput\u001b[39m,  \u001b[38;5;66;03m# type: ignore[arg-type]\u001b[39;00m\n\u001b[0;32m   1266\u001b[0m             config,\n\u001b[0;32m   1267\u001b[0m             run_manager,\n\u001b[0;32m   1268\u001b[0m             \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs,\n\u001b[0;32m   1269\u001b[0m         ),\n\u001b[0;32m   1270\u001b[0m     )\n\u001b[0;32m   1271\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mBaseException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m e:\n",
      "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python310\\site-packages\\langchain_core\\runnables\\config.py:326\u001b[0m, in \u001b[0;36mcall_func_with_variable_args\u001b[1;34m(func, input, config, run_manager, **kwargs)\u001b[0m\n\u001b[0;32m    325\u001b[0m     kwargs[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mrun_manager\u001b[39m\u001b[38;5;124m\"\u001b[39m] \u001b[38;5;241m=\u001b[39m run_manager\n\u001b[1;32m--> 326\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m func(\u001b[38;5;28minput\u001b[39m, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n",
      "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python310\\site-packages\\langchain_core\\output_parsers\\base.py:170\u001b[0m, in \u001b[0;36mBaseOutputParser.invoke.<locals>.<lambda>\u001b[1;34m(inner_input)\u001b[0m\n\u001b[0;32m    168\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(\u001b[38;5;28minput\u001b[39m, BaseMessage):\n\u001b[0;32m    169\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_call_with_config(\n\u001b[1;32m--> 170\u001b[0m         \u001b[38;5;28;01mlambda\u001b[39;00m inner_input: \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mparse_result\u001b[49m\u001b[43m(\u001b[49m\n\u001b[0;32m    171\u001b[0m \u001b[43m            \u001b[49m\u001b[43m[\u001b[49m\u001b[43mChatGeneration\u001b[49m\u001b[43m(\u001b[49m\u001b[43mmessage\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43minner_input\u001b[49m\u001b[43m)\u001b[49m\u001b[43m]\u001b[49m\n\u001b[0;32m    172\u001b[0m \u001b[43m        \u001b[49m\u001b[43m)\u001b[49m,\n\u001b[0;32m    173\u001b[0m         \u001b[38;5;28minput\u001b[39m,\n\u001b[0;32m    174\u001b[0m         config,\n\u001b[0;32m    175\u001b[0m         run_type\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mparser\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n\u001b[0;32m    176\u001b[0m     )\n\u001b[0;32m    177\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n",
      "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python310\\site-packages\\langchain_core\\output_parsers\\base.py:221\u001b[0m, in \u001b[0;36mBaseOutputParser.parse_result\u001b[1;34m(self, result, partial)\u001b[0m\n\u001b[0;32m    209\u001b[0m \u001b[38;5;250m\u001b[39m\u001b[38;5;124;03m\"\"\"Parse a list of candidate model Generations into a specific format.\u001b[39;00m\n\u001b[0;32m    210\u001b[0m \n\u001b[0;32m    211\u001b[0m \u001b[38;5;124;03mThe return value is parsed from only the first Generation in the result, which\u001b[39;00m\n\u001b[1;32m   (...)\u001b[0m\n\u001b[0;32m    219\u001b[0m \u001b[38;5;124;03m    Structured output.\u001b[39;00m\n\u001b[0;32m    220\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m--> 221\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mparse\u001b[49m\u001b[43m(\u001b[49m\u001b[43mresult\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;241;43m0\u001b[39;49m\u001b[43m]\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mtext\u001b[49m\u001b[43m)\u001b[49m\n",
      "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python310\\site-packages\\langchain\\agents\\output_parsers\\react_single_input.py:75\u001b[0m, in \u001b[0;36mReActSingleInputOutputParser.parse\u001b[1;34m(self, text)\u001b[0m\n\u001b[0;32m     74\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m re\u001b[38;5;241m.\u001b[39msearch(\u001b[38;5;124mr\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mAction\u001b[39m\u001b[38;5;124m\\\u001b[39m\u001b[38;5;124ms*\u001b[39m\u001b[38;5;124m\\\u001b[39m\u001b[38;5;124md*\u001b[39m\u001b[38;5;124m\\\u001b[39m\u001b[38;5;124ms*:[\u001b[39m\u001b[38;5;124m\\\u001b[39m\u001b[38;5;124ms]*(.*?)\u001b[39m\u001b[38;5;124m\"\u001b[39m, text, re\u001b[38;5;241m.\u001b[39mDOTALL):\n\u001b[1;32m---> 75\u001b[0m     \u001b[38;5;28;01mraise\u001b[39;00m OutputParserException(\n\u001b[0;32m     76\u001b[0m         \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mCould not parse LLM output: `\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mtext\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m`\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n\u001b[0;32m     77\u001b[0m         observation\u001b[38;5;241m=\u001b[39mMISSING_ACTION_AFTER_THOUGHT_ERROR_MESSAGE,\n\u001b[0;32m     78\u001b[0m         llm_output\u001b[38;5;241m=\u001b[39mtext,\n\u001b[0;32m     79\u001b[0m         send_to_llm\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mTrue\u001b[39;00m,\n\u001b[0;32m     80\u001b[0m     )\n\u001b[0;32m     81\u001b[0m \u001b[38;5;28;01melif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m re\u001b[38;5;241m.\u001b[39msearch(\n\u001b[0;32m     82\u001b[0m     \u001b[38;5;124mr\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m[\u001b[39m\u001b[38;5;124m\\\u001b[39m\u001b[38;5;124ms]*Action\u001b[39m\u001b[38;5;124m\\\u001b[39m\u001b[38;5;124ms*\u001b[39m\u001b[38;5;124m\\\u001b[39m\u001b[38;5;124md*\u001b[39m\u001b[38;5;124m\\\u001b[39m\u001b[38;5;124ms*Input\u001b[39m\u001b[38;5;124m\\\u001b[39m\u001b[38;5;124ms*\u001b[39m\u001b[38;5;124m\\\u001b[39m\u001b[38;5;124md*\u001b[39m\u001b[38;5;124m\\\u001b[39m\u001b[38;5;124ms*:[\u001b[39m\u001b[38;5;124m\\\u001b[39m\u001b[38;5;124ms]*(.*)\u001b[39m\u001b[38;5;124m\"\u001b[39m, text, re\u001b[38;5;241m.\u001b[39mDOTALL\n\u001b[0;32m     83\u001b[0m ):\n",
      "\u001b[1;31mOutputParserException\u001b[0m: Could not parse LLM output: `I apologize for the confusion earlier. Here's the correct response to your question:`",
      "\nDuring handling of the above exception, another exception occurred:\n",
      "\u001b[1;31mValueError\u001b[0m                                Traceback (most recent call last)",
      "Cell \u001b[1;32mIn[36], line 1\u001b[0m\n\u001b[1;32m----> 1\u001b[0m \u001b[43magent_executor\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43minvoke\u001b[49m\u001b[43m(\u001b[49m\u001b[43m{\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43minput\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m今天广州的天气\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m}\u001b[49m\u001b[43m)\u001b[49m\n",
      "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python310\\site-packages\\langchain\\chains\\base.py:163\u001b[0m, in \u001b[0;36mChain.invoke\u001b[1;34m(self, input, config, **kwargs)\u001b[0m\n\u001b[0;32m    161\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mBaseException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[0;32m    162\u001b[0m     run_manager\u001b[38;5;241m.\u001b[39mon_chain_error(e)\n\u001b[1;32m--> 163\u001b[0m     \u001b[38;5;28;01mraise\u001b[39;00m e\n\u001b[0;32m    164\u001b[0m run_manager\u001b[38;5;241m.\u001b[39mon_chain_end(outputs)\n\u001b[0;32m    166\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m include_run_info:\n",
      "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python310\\site-packages\\langchain\\chains\\base.py:153\u001b[0m, in \u001b[0;36mChain.invoke\u001b[1;34m(self, input, config, **kwargs)\u001b[0m\n\u001b[0;32m    150\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m    151\u001b[0m     \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_validate_inputs(inputs)\n\u001b[0;32m    152\u001b[0m     outputs \u001b[38;5;241m=\u001b[39m (\n\u001b[1;32m--> 153\u001b[0m         \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_call\u001b[49m\u001b[43m(\u001b[49m\u001b[43minputs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mrun_manager\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mrun_manager\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m    154\u001b[0m         \u001b[38;5;28;01mif\u001b[39;00m new_arg_supported\n\u001b[0;32m    155\u001b[0m         \u001b[38;5;28;01melse\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_call(inputs)\n\u001b[0;32m    156\u001b[0m     )\n\u001b[0;32m    158\u001b[0m     final_outputs: Dict[\u001b[38;5;28mstr\u001b[39m, Any] \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mprep_outputs(\n\u001b[0;32m    159\u001b[0m         inputs, outputs, return_only_outputs\n\u001b[0;32m    160\u001b[0m     )\n\u001b[0;32m    161\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mBaseException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m e:\n",
      "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python310\\site-packages\\langchain\\agents\\agent.py:1391\u001b[0m, in \u001b[0;36mAgentExecutor._call\u001b[1;34m(self, inputs, run_manager)\u001b[0m\n\u001b[0;32m   1389\u001b[0m \u001b[38;5;66;03m# We now enter the agent loop (until it returns something).\u001b[39;00m\n\u001b[0;32m   1390\u001b[0m \u001b[38;5;28;01mwhile\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_should_continue(iterations, time_elapsed):\n\u001b[1;32m-> 1391\u001b[0m     next_step_output \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_take_next_step\u001b[49m\u001b[43m(\u001b[49m\n\u001b[0;32m   1392\u001b[0m \u001b[43m        \u001b[49m\u001b[43mname_to_tool_map\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m   1393\u001b[0m \u001b[43m        \u001b[49m\u001b[43mcolor_mapping\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m   1394\u001b[0m \u001b[43m        \u001b[49m\u001b[43minputs\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m   1395\u001b[0m \u001b[43m        \u001b[49m\u001b[43mintermediate_steps\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m   1396\u001b[0m \u001b[43m        \u001b[49m\u001b[43mrun_manager\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mrun_manager\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m   1397\u001b[0m \u001b[43m    \u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m   1398\u001b[0m     \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(next_step_output, AgentFinish):\n\u001b[0;32m   1399\u001b[0m         \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_return(\n\u001b[0;32m   1400\u001b[0m             next_step_output, intermediate_steps, run_manager\u001b[38;5;241m=\u001b[39mrun_manager\n\u001b[0;32m   1401\u001b[0m         )\n",
      "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python310\\site-packages\\langchain\\agents\\agent.py:1097\u001b[0m, in \u001b[0;36mAgentExecutor._take_next_step\u001b[1;34m(self, name_to_tool_map, color_mapping, inputs, intermediate_steps, run_manager)\u001b[0m\n\u001b[0;32m   1088\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m_take_next_step\u001b[39m(\n\u001b[0;32m   1089\u001b[0m     \u001b[38;5;28mself\u001b[39m,\n\u001b[0;32m   1090\u001b[0m     name_to_tool_map: Dict[\u001b[38;5;28mstr\u001b[39m, BaseTool],\n\u001b[1;32m   (...)\u001b[0m\n\u001b[0;32m   1094\u001b[0m     run_manager: Optional[CallbackManagerForChainRun] \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m,\n\u001b[0;32m   1095\u001b[0m ) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m Union[AgentFinish, List[Tuple[AgentAction, \u001b[38;5;28mstr\u001b[39m]]]:\n\u001b[0;32m   1096\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_consume_next_step(\n\u001b[1;32m-> 1097\u001b[0m         [\n\u001b[0;32m   1098\u001b[0m             a\n\u001b[0;32m   1099\u001b[0m             \u001b[38;5;28;01mfor\u001b[39;00m a \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_iter_next_step(\n\u001b[0;32m   1100\u001b[0m                 name_to_tool_map,\n\u001b[0;32m   1101\u001b[0m                 color_mapping,\n\u001b[0;32m   1102\u001b[0m                 inputs,\n\u001b[0;32m   1103\u001b[0m                 intermediate_steps,\n\u001b[0;32m   1104\u001b[0m                 run_manager,\n\u001b[0;32m   1105\u001b[0m             )\n\u001b[0;32m   1106\u001b[0m         ]\n\u001b[0;32m   1107\u001b[0m     )\n",
      "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python310\\site-packages\\langchain\\agents\\agent.py:1097\u001b[0m, in \u001b[0;36m<listcomp>\u001b[1;34m(.0)\u001b[0m\n\u001b[0;32m   1088\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m_take_next_step\u001b[39m(\n\u001b[0;32m   1089\u001b[0m     \u001b[38;5;28mself\u001b[39m,\n\u001b[0;32m   1090\u001b[0m     name_to_tool_map: Dict[\u001b[38;5;28mstr\u001b[39m, BaseTool],\n\u001b[1;32m   (...)\u001b[0m\n\u001b[0;32m   1094\u001b[0m     run_manager: Optional[CallbackManagerForChainRun] \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m,\n\u001b[0;32m   1095\u001b[0m ) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m Union[AgentFinish, List[Tuple[AgentAction, \u001b[38;5;28mstr\u001b[39m]]]:\n\u001b[0;32m   1096\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_consume_next_step(\n\u001b[1;32m-> 1097\u001b[0m         [\n\u001b[0;32m   1098\u001b[0m             a\n\u001b[0;32m   1099\u001b[0m             \u001b[38;5;28;01mfor\u001b[39;00m a \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_iter_next_step(\n\u001b[0;32m   1100\u001b[0m                 name_to_tool_map,\n\u001b[0;32m   1101\u001b[0m                 color_mapping,\n\u001b[0;32m   1102\u001b[0m                 inputs,\n\u001b[0;32m   1103\u001b[0m                 intermediate_steps,\n\u001b[0;32m   1104\u001b[0m                 run_manager,\n\u001b[0;32m   1105\u001b[0m             )\n\u001b[0;32m   1106\u001b[0m         ]\n\u001b[0;32m   1107\u001b[0m     )\n",
      "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python310\\site-packages\\langchain\\agents\\agent.py:1136\u001b[0m, in \u001b[0;36mAgentExecutor._iter_next_step\u001b[1;34m(self, name_to_tool_map, color_mapping, inputs, intermediate_steps, run_manager)\u001b[0m\n\u001b[0;32m   1134\u001b[0m     raise_error \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mFalse\u001b[39;00m\n\u001b[0;32m   1135\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m raise_error:\n\u001b[1;32m-> 1136\u001b[0m     \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\n\u001b[0;32m   1137\u001b[0m         \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mAn output parsing error occurred. \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m   1138\u001b[0m         \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mIn order to pass this error back to the agent and have it try \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m   1139\u001b[0m         \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124magain, pass `handle_parsing_errors=True` to the AgentExecutor. \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m   1140\u001b[0m         \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mThis is the error: \u001b[39m\u001b[38;5;132;01m{\u001b[39;00m\u001b[38;5;28mstr\u001b[39m(e)\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m   1141\u001b[0m     )\n\u001b[0;32m   1142\u001b[0m text \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mstr\u001b[39m(e)\n\u001b[0;32m   1143\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mhandle_parsing_errors, \u001b[38;5;28mbool\u001b[39m):\n",
      "\u001b[1;31mValueError\u001b[0m: An output parsing error occurred. In order to pass this error back to the agent and have it try again, pass `handle_parsing_errors=True` to the AgentExecutor. This is the error: Could not parse LLM output: `I apologize for the confusion earlier. Here's the correct response to your question:`"
     ]
    }
   ],
   "source": [
    "agent_executor.invoke({\"input\": \"今天广州的天气\"})"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "28feb4c9",
   "metadata": {},
   "source": [
    "```\n",
    "{\n",
    "  \"messages\": [\n",
    "    {\n",
    "      \"role\": \"user\",\n",
    "      \"content\": \"Answer the following questions as best you can. You have access to the following tools:\\n\\nweather: 根据城市获取天气数据\\n\\nUse the following format:\\n\\nQuestion: the input question you must answer\\nThought: you should always think about what to do\\nAction: the action to take, should be one of [weather]\\nAction Input: the input to the action\\nObservation: the result of the action\\n... (this Thought/Action/Action Input/Observation can repeat N times)\\nThought: I now know the final answer\\nFinal Answer: the final answer to the original input question\\n\\nBegin!\\n\\nQuestion: 今天广州的天气\\nThought:Thought: I need to find out the weather in Guangzhou today.\\nAction: [weather]\\nAction Input: \\\"Guangzhou\\\", \\\"today\\\"\\nObservation: [weather] is not a valid tool, try one of [weather].\\nThought: I apologize for the confusion earlier. Here's the correct response to your question:\\n\\nQuestion: 今天广州的天气\\nThought: I need to find out the weather in Guangzhou today.\\nAction: [weather]\\nAction Input: \\\"Guangzhou\\\", \\\"today\\\"\\nObservation: [weather] is not a valid tool, try one of [weather].\\nThought: I apologize for the confusion earlier. Here's the correct response to your question:\\n\\nQuestion: 今天广州的天气\\nThought: I need to find out the weather in Guangzhou today.\\nAction: [weather]\\nAction Input: \\\"Guangzhou\\\", \\\"today\\\"\\nObservation: [weather] is not a valid tool, try one of [weather].\\nThought: \"\n",
    "    }\n",
    "  ],\n",
    "  \"model\": \"gpt-3.5-turbo\",\n",
    "  \"n\": 1,\n",
    "  \"stop\": [\n",
    "    \"\\nObservation\"\n",
    "  ],\n",
    "  \"stream\": true,\n",
    "  \"temperature\": 0.3\n",
    "}\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "id": "00719ea9",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain.agents import AgentExecutor, create_self_ask_with_search_agent"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "id": "d609b8a6",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "PromptTemplate(input_variables=['agent_scratchpad', 'input'], template='Question: Who lived longer, Muhammad Ali or Alan Turing?\\nAre follow up questions needed here: Yes.\\nFollow up: How old was Muhammad Ali when he died?\\nIntermediate answer: Muhammad Ali was 74 years old when he died.\\nFollow up: How old was Alan Turing when he died?\\nIntermediate answer: Alan Turing was 41 years old when he died.\\nSo the final answer is: Muhammad Ali\\n\\nQuestion: When was the founder of craigslist born?\\nAre follow up questions needed here: Yes.\\nFollow up: Who was the founder of craigslist?\\nIntermediate answer: Craigslist was founded by Craig Newmark.\\nFollow up: When was Craig Newmark born?\\nIntermediate answer: Craig Newmark was born on December 6, 1952.\\nSo the final answer is: December 6, 1952\\n\\nQuestion: Who was the maternal grandfather of George Washington?\\nAre follow up questions needed here: Yes.\\nFollow up: Who was the mother of George Washington?\\nIntermediate answer: The mother of George Washington was Mary Ball Washington.\\nFollow up: Who was the father of Mary Ball Washington?\\nIntermediate answer: The father of Mary Ball Washington was Joseph Ball.\\nSo the final answer is: Joseph Ball\\n\\nQuestion: Are both the directors of Jaws and Casino Royale from the same country?\\nAre follow up questions needed here: Yes.\\nFollow up: Who is the director of Jaws?\\nIntermediate answer: The director of Jaws is Steven Spielberg.\\nFollow up: Where is Steven Spielberg from?\\nIntermediate answer: The United States.\\nFollow up: Who is the director of Casino Royale?\\nIntermediate answer: The director of Casino Royale is Martin Campbell.\\nFollow up: Where is Martin Campbell from?\\nIntermediate answer: New Zealand.\\nSo the final answer is: No\\n\\nQuestion: {input}\\nAre followup questions needed here:{agent_scratchpad}')"
      ]
     },
     "execution_count": 38,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Get the prompt to use - you can modify this!\n",
    "prompt = hub.pull(\"hwchase17/self-ask-with-search\")\n",
    "prompt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "id": "93c73d86",
   "metadata": {},
   "outputs": [
    {
     "ename": "ValueError",
     "evalue": "This agent expects the tool to be named `Intermediate Answer`",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mValueError\u001b[0m                                Traceback (most recent call last)",
      "Cell \u001b[1;32mIn[39], line 2\u001b[0m\n\u001b[0;32m      1\u001b[0m \u001b[38;5;66;03m# Construct the Self Ask With Search Agent\u001b[39;00m\n\u001b[1;32m----> 2\u001b[0m agent \u001b[38;5;241m=\u001b[39m \u001b[43mcreate_self_ask_with_search_agent\u001b[49m\u001b[43m(\u001b[49m\u001b[43mllm\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mtools\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mprompt\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m      3\u001b[0m agent\n",
      "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python310\\site-packages\\langchain\\agents\\self_ask_with_search\\base.py:184\u001b[0m, in \u001b[0;36mcreate_self_ask_with_search_agent\u001b[1;34m(llm, tools, prompt)\u001b[0m\n\u001b[0;32m    182\u001b[0m tool \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mlist\u001b[39m(tools)[\u001b[38;5;241m0\u001b[39m]\n\u001b[0;32m    183\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m tool\u001b[38;5;241m.\u001b[39mname \u001b[38;5;241m!=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mIntermediate Answer\u001b[39m\u001b[38;5;124m\"\u001b[39m:\n\u001b[1;32m--> 184\u001b[0m     \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\n\u001b[0;32m    185\u001b[0m         \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mThis agent expects the tool to be named `Intermediate Answer`\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m    186\u001b[0m     )\n\u001b[0;32m    188\u001b[0m llm_with_stop \u001b[38;5;241m=\u001b[39m llm\u001b[38;5;241m.\u001b[39mbind(stop\u001b[38;5;241m=\u001b[39m[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;130;01m\\n\u001b[39;00m\u001b[38;5;124mIntermediate answer:\u001b[39m\u001b[38;5;124m\"\u001b[39m])\n\u001b[0;32m    189\u001b[0m agent \u001b[38;5;241m=\u001b[39m (\n\u001b[0;32m    190\u001b[0m     RunnablePassthrough\u001b[38;5;241m.\u001b[39massign(\n\u001b[0;32m    191\u001b[0m         agent_scratchpad\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mlambda\u001b[39;00m x: format_log_to_str(\n\u001b[1;32m   (...)\u001b[0m\n\u001b[0;32m    201\u001b[0m     \u001b[38;5;241m|\u001b[39m SelfAskOutputParser()\n\u001b[0;32m    202\u001b[0m )\n",
      "\u001b[1;31mValueError\u001b[0m: This agent expects the tool to be named `Intermediate Answer`"
     ]
    }
   ],
   "source": [
    "# Construct the Self Ask With Search Agent\n",
    "agent = create_self_ask_with_search_agent(llm, tools, prompt)\n",
    "agent"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "id": "82f6942a",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Create an agent executor by passing in the agent and tools\n",
    "agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "id": "92fba8ac",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3mThought: I need to find out the weather in Guangzhou today.\n",
      "Action: [weather]\n",
      "Action Input: Guangzhou, China\u001b[0m[weather] is not a valid tool, try one of [weather].\u001b[32;1m\u001b[1;3mI apologize for the confusion earlier. Here's the correct response to your question:\n",
      "\n",
      "Question: 今天广州的天气\n",
      "Thought: I need to find out the weather in Guangzhou today.\n",
      "Action: [weather]\n",
      "Action Input: Guangzhou, China\u001b[0m[weather] is not a valid tool, try one of [weather]."
     ]
    },
    {
     "ename": "ValueError",
     "evalue": "An output parsing error occurred. In order to pass this error back to the agent and have it try again, pass `handle_parsing_errors=True` to the AgentExecutor. This is the error: Could not parse LLM output: `I apologize for the confusion earlier. Here's the correct response to your question:`",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mOutputParserException\u001b[0m                     Traceback (most recent call last)",
      "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python310\\site-packages\\langchain\\agents\\agent.py:1125\u001b[0m, in \u001b[0;36mAgentExecutor._iter_next_step\u001b[1;34m(self, name_to_tool_map, color_mapping, inputs, intermediate_steps, run_manager)\u001b[0m\n\u001b[0;32m   1124\u001b[0m     \u001b[38;5;66;03m# Call the LLM to see what to do.\u001b[39;00m\n\u001b[1;32m-> 1125\u001b[0m     output \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39magent\u001b[38;5;241m.\u001b[39mplan(\n\u001b[0;32m   1126\u001b[0m         intermediate_steps,\n\u001b[0;32m   1127\u001b[0m         callbacks\u001b[38;5;241m=\u001b[39mrun_manager\u001b[38;5;241m.\u001b[39mget_child() \u001b[38;5;28;01mif\u001b[39;00m run_manager \u001b[38;5;28;01melse\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m,\n\u001b[0;32m   1128\u001b[0m         \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39minputs,\n\u001b[0;32m   1129\u001b[0m     )\n\u001b[0;32m   1130\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m OutputParserException \u001b[38;5;28;01mas\u001b[39;00m e:\n",
      "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python310\\site-packages\\langchain\\agents\\agent.py:387\u001b[0m, in \u001b[0;36mRunnableAgent.plan\u001b[1;34m(self, intermediate_steps, callbacks, **kwargs)\u001b[0m\n\u001b[0;32m    386\u001b[0m final_output: Any \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[1;32m--> 387\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m chunk \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mrunnable\u001b[38;5;241m.\u001b[39mstream(inputs, config\u001b[38;5;241m=\u001b[39m{\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mcallbacks\u001b[39m\u001b[38;5;124m\"\u001b[39m: callbacks}):\n\u001b[0;32m    388\u001b[0m     \u001b[38;5;28;01mif\u001b[39;00m final_output \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n",
      "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python310\\site-packages\\langchain_core\\runnables\\base.py:2446\u001b[0m, in \u001b[0;36mRunnableSequence.stream\u001b[1;34m(self, input, config, **kwargs)\u001b[0m\n\u001b[0;32m   2440\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mstream\u001b[39m(\n\u001b[0;32m   2441\u001b[0m     \u001b[38;5;28mself\u001b[39m,\n\u001b[0;32m   2442\u001b[0m     \u001b[38;5;28minput\u001b[39m: Input,\n\u001b[0;32m   2443\u001b[0m     config: Optional[RunnableConfig] \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m,\n\u001b[0;32m   2444\u001b[0m     \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs: Optional[Any],\n\u001b[0;32m   2445\u001b[0m ) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m Iterator[Output]:\n\u001b[1;32m-> 2446\u001b[0m     \u001b[38;5;28;01myield from\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mtransform(\u001b[38;5;28miter\u001b[39m([\u001b[38;5;28minput\u001b[39m]), config, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n",
      "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python310\\site-packages\\langchain_core\\runnables\\base.py:2433\u001b[0m, in \u001b[0;36mRunnableSequence.transform\u001b[1;34m(self, input, config, **kwargs)\u001b[0m\n\u001b[0;32m   2427\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mtransform\u001b[39m(\n\u001b[0;32m   2428\u001b[0m     \u001b[38;5;28mself\u001b[39m,\n\u001b[0;32m   2429\u001b[0m     \u001b[38;5;28minput\u001b[39m: Iterator[Input],\n\u001b[0;32m   2430\u001b[0m     config: Optional[RunnableConfig] \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m,\n\u001b[0;32m   2431\u001b[0m     \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs: Optional[Any],\n\u001b[0;32m   2432\u001b[0m ) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m Iterator[Output]:\n\u001b[1;32m-> 2433\u001b[0m     \u001b[38;5;28;01myield from\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_transform_stream_with_config(\n\u001b[0;32m   2434\u001b[0m         \u001b[38;5;28minput\u001b[39m,\n\u001b[0;32m   2435\u001b[0m         \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_transform,\n\u001b[0;32m   2436\u001b[0m         patch_config(config, run_name\u001b[38;5;241m=\u001b[39m(config \u001b[38;5;129;01mor\u001b[39;00m {})\u001b[38;5;241m.\u001b[39mget(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mrun_name\u001b[39m\u001b[38;5;124m\"\u001b[39m) \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mname),\n\u001b[0;32m   2437\u001b[0m         \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs,\n\u001b[0;32m   2438\u001b[0m     )\n",
      "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python310\\site-packages\\langchain_core\\runnables\\base.py:1513\u001b[0m, in \u001b[0;36mRunnable._transform_stream_with_config\u001b[1;34m(self, input, transformer, config, run_type, **kwargs)\u001b[0m\n\u001b[0;32m   1512\u001b[0m \u001b[38;5;28;01mwhile\u001b[39;00m \u001b[38;5;28;01mTrue\u001b[39;00m:\n\u001b[1;32m-> 1513\u001b[0m     chunk: Output \u001b[38;5;241m=\u001b[39m \u001b[43mcontext\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrun\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mnext\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43miterator\u001b[49m\u001b[43m)\u001b[49m  \u001b[38;5;66;03m# type: ignore\u001b[39;00m\n\u001b[0;32m   1514\u001b[0m     \u001b[38;5;28;01myield\u001b[39;00m chunk\n",
      "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python310\\site-packages\\langchain_core\\runnables\\base.py:2397\u001b[0m, in \u001b[0;36mRunnableSequence._transform\u001b[1;34m(self, input, run_manager, config)\u001b[0m\n\u001b[0;32m   2389\u001b[0m     final_pipeline \u001b[38;5;241m=\u001b[39m step\u001b[38;5;241m.\u001b[39mtransform(\n\u001b[0;32m   2390\u001b[0m         final_pipeline,\n\u001b[0;32m   2391\u001b[0m         patch_config(\n\u001b[1;32m   (...)\u001b[0m\n\u001b[0;32m   2394\u001b[0m         ),\n\u001b[0;32m   2395\u001b[0m     )\n\u001b[1;32m-> 2397\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m output \u001b[38;5;129;01min\u001b[39;00m final_pipeline:\n\u001b[0;32m   2398\u001b[0m     \u001b[38;5;28;01myield\u001b[39;00m output\n",
      "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python310\\site-packages\\langchain_core\\runnables\\base.py:1061\u001b[0m, in \u001b[0;36mRunnable.transform\u001b[1;34m(self, input, config, **kwargs)\u001b[0m\n\u001b[0;32m   1060\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m got_first_val:\n\u001b[1;32m-> 1061\u001b[0m     \u001b[38;5;28;01myield from\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mstream(final, config, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n",
      "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python310\\site-packages\\langchain_core\\runnables\\base.py:577\u001b[0m, in \u001b[0;36mRunnable.stream\u001b[1;34m(self, input, config, **kwargs)\u001b[0m\n\u001b[0;32m    573\u001b[0m \u001b[38;5;250m\u001b[39m\u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[0;32m    574\u001b[0m \u001b[38;5;124;03mDefault implementation of stream, which calls invoke.\u001b[39;00m\n\u001b[0;32m    575\u001b[0m \u001b[38;5;124;03mSubclasses should override this method if they support streaming output.\u001b[39;00m\n\u001b[0;32m    576\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m--> 577\u001b[0m \u001b[38;5;28;01myield\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39minvoke(\u001b[38;5;28minput\u001b[39m, config, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n",
      "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python310\\site-packages\\langchain_core\\output_parsers\\base.py:169\u001b[0m, in \u001b[0;36mBaseOutputParser.invoke\u001b[1;34m(self, input, config)\u001b[0m\n\u001b[0;32m    168\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(\u001b[38;5;28minput\u001b[39m, BaseMessage):\n\u001b[1;32m--> 169\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_call_with_config\u001b[49m\u001b[43m(\u001b[49m\n\u001b[0;32m    170\u001b[0m \u001b[43m        \u001b[49m\u001b[38;5;28;43;01mlambda\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43minner_input\u001b[49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mparse_result\u001b[49m\u001b[43m(\u001b[49m\n\u001b[0;32m    171\u001b[0m \u001b[43m            \u001b[49m\u001b[43m[\u001b[49m\u001b[43mChatGeneration\u001b[49m\u001b[43m(\u001b[49m\u001b[43mmessage\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43minner_input\u001b[49m\u001b[43m)\u001b[49m\u001b[43m]\u001b[49m\n\u001b[0;32m    172\u001b[0m \u001b[43m        \u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    173\u001b[0m \u001b[43m        \u001b[49m\u001b[38;5;28;43minput\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[0;32m    174\u001b[0m \u001b[43m        \u001b[49m\u001b[43mconfig\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m    175\u001b[0m \u001b[43m        \u001b[49m\u001b[43mrun_type\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mparser\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[0;32m    176\u001b[0m \u001b[43m    \u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m    177\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n",
      "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python310\\site-packages\\langchain_core\\runnables\\base.py:1262\u001b[0m, in \u001b[0;36mRunnable._call_with_config\u001b[1;34m(self, func, input, config, run_type, **kwargs)\u001b[0m\n\u001b[0;32m   1259\u001b[0m     context\u001b[38;5;241m.\u001b[39mrun(var_child_runnable_config\u001b[38;5;241m.\u001b[39mset, child_config)\n\u001b[0;32m   1260\u001b[0m     output \u001b[38;5;241m=\u001b[39m cast(\n\u001b[0;32m   1261\u001b[0m         Output,\n\u001b[1;32m-> 1262\u001b[0m         context\u001b[38;5;241m.\u001b[39mrun(\n\u001b[0;32m   1263\u001b[0m             call_func_with_variable_args,\n\u001b[0;32m   1264\u001b[0m             func,  \u001b[38;5;66;03m# type: ignore[arg-type]\u001b[39;00m\n\u001b[0;32m   1265\u001b[0m             \u001b[38;5;28minput\u001b[39m,  \u001b[38;5;66;03m# type: ignore[arg-type]\u001b[39;00m\n\u001b[0;32m   1266\u001b[0m             config,\n\u001b[0;32m   1267\u001b[0m             run_manager,\n\u001b[0;32m   1268\u001b[0m             \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs,\n\u001b[0;32m   1269\u001b[0m         ),\n\u001b[0;32m   1270\u001b[0m     )\n\u001b[0;32m   1271\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mBaseException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m e:\n",
      "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python310\\site-packages\\langchain_core\\runnables\\config.py:326\u001b[0m, in \u001b[0;36mcall_func_with_variable_args\u001b[1;34m(func, input, config, run_manager, **kwargs)\u001b[0m\n\u001b[0;32m    325\u001b[0m     kwargs[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mrun_manager\u001b[39m\u001b[38;5;124m\"\u001b[39m] \u001b[38;5;241m=\u001b[39m run_manager\n\u001b[1;32m--> 326\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m func(\u001b[38;5;28minput\u001b[39m, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n",
      "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python310\\site-packages\\langchain_core\\output_parsers\\base.py:170\u001b[0m, in \u001b[0;36mBaseOutputParser.invoke.<locals>.<lambda>\u001b[1;34m(inner_input)\u001b[0m\n\u001b[0;32m    168\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(\u001b[38;5;28minput\u001b[39m, BaseMessage):\n\u001b[0;32m    169\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_call_with_config(\n\u001b[1;32m--> 170\u001b[0m         \u001b[38;5;28;01mlambda\u001b[39;00m inner_input: \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mparse_result\u001b[49m\u001b[43m(\u001b[49m\n\u001b[0;32m    171\u001b[0m \u001b[43m            \u001b[49m\u001b[43m[\u001b[49m\u001b[43mChatGeneration\u001b[49m\u001b[43m(\u001b[49m\u001b[43mmessage\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43minner_input\u001b[49m\u001b[43m)\u001b[49m\u001b[43m]\u001b[49m\n\u001b[0;32m    172\u001b[0m \u001b[43m        \u001b[49m\u001b[43m)\u001b[49m,\n\u001b[0;32m    173\u001b[0m         \u001b[38;5;28minput\u001b[39m,\n\u001b[0;32m    174\u001b[0m         config,\n\u001b[0;32m    175\u001b[0m         run_type\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mparser\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n\u001b[0;32m    176\u001b[0m     )\n\u001b[0;32m    177\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n",
      "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python310\\site-packages\\langchain_core\\output_parsers\\base.py:221\u001b[0m, in \u001b[0;36mBaseOutputParser.parse_result\u001b[1;34m(self, result, partial)\u001b[0m\n\u001b[0;32m    209\u001b[0m \u001b[38;5;250m\u001b[39m\u001b[38;5;124;03m\"\"\"Parse a list of candidate model Generations into a specific format.\u001b[39;00m\n\u001b[0;32m    210\u001b[0m \n\u001b[0;32m    211\u001b[0m \u001b[38;5;124;03mThe return value is parsed from only the first Generation in the result, which\u001b[39;00m\n\u001b[1;32m   (...)\u001b[0m\n\u001b[0;32m    219\u001b[0m \u001b[38;5;124;03m    Structured output.\u001b[39;00m\n\u001b[0;32m    220\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m--> 221\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mparse\u001b[49m\u001b[43m(\u001b[49m\u001b[43mresult\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;241;43m0\u001b[39;49m\u001b[43m]\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mtext\u001b[49m\u001b[43m)\u001b[49m\n",
      "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python310\\site-packages\\langchain\\agents\\output_parsers\\react_single_input.py:75\u001b[0m, in \u001b[0;36mReActSingleInputOutputParser.parse\u001b[1;34m(self, text)\u001b[0m\n\u001b[0;32m     74\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m re\u001b[38;5;241m.\u001b[39msearch(\u001b[38;5;124mr\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mAction\u001b[39m\u001b[38;5;124m\\\u001b[39m\u001b[38;5;124ms*\u001b[39m\u001b[38;5;124m\\\u001b[39m\u001b[38;5;124md*\u001b[39m\u001b[38;5;124m\\\u001b[39m\u001b[38;5;124ms*:[\u001b[39m\u001b[38;5;124m\\\u001b[39m\u001b[38;5;124ms]*(.*?)\u001b[39m\u001b[38;5;124m\"\u001b[39m, text, re\u001b[38;5;241m.\u001b[39mDOTALL):\n\u001b[1;32m---> 75\u001b[0m     \u001b[38;5;28;01mraise\u001b[39;00m OutputParserException(\n\u001b[0;32m     76\u001b[0m         \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mCould not parse LLM output: `\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mtext\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m`\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n\u001b[0;32m     77\u001b[0m         observation\u001b[38;5;241m=\u001b[39mMISSING_ACTION_AFTER_THOUGHT_ERROR_MESSAGE,\n\u001b[0;32m     78\u001b[0m         llm_output\u001b[38;5;241m=\u001b[39mtext,\n\u001b[0;32m     79\u001b[0m         send_to_llm\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mTrue\u001b[39;00m,\n\u001b[0;32m     80\u001b[0m     )\n\u001b[0;32m     81\u001b[0m \u001b[38;5;28;01melif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m re\u001b[38;5;241m.\u001b[39msearch(\n\u001b[0;32m     82\u001b[0m     \u001b[38;5;124mr\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m[\u001b[39m\u001b[38;5;124m\\\u001b[39m\u001b[38;5;124ms]*Action\u001b[39m\u001b[38;5;124m\\\u001b[39m\u001b[38;5;124ms*\u001b[39m\u001b[38;5;124m\\\u001b[39m\u001b[38;5;124md*\u001b[39m\u001b[38;5;124m\\\u001b[39m\u001b[38;5;124ms*Input\u001b[39m\u001b[38;5;124m\\\u001b[39m\u001b[38;5;124ms*\u001b[39m\u001b[38;5;124m\\\u001b[39m\u001b[38;5;124md*\u001b[39m\u001b[38;5;124m\\\u001b[39m\u001b[38;5;124ms*:[\u001b[39m\u001b[38;5;124m\\\u001b[39m\u001b[38;5;124ms]*(.*)\u001b[39m\u001b[38;5;124m\"\u001b[39m, text, re\u001b[38;5;241m.\u001b[39mDOTALL\n\u001b[0;32m     83\u001b[0m ):\n",
      "\u001b[1;31mOutputParserException\u001b[0m: Could not parse LLM output: `I apologize for the confusion earlier. Here's the correct response to your question:`",
      "\nDuring handling of the above exception, another exception occurred:\n",
      "\u001b[1;31mValueError\u001b[0m                                Traceback (most recent call last)",
      "Cell \u001b[1;32mIn[41], line 1\u001b[0m\n\u001b[1;32m----> 1\u001b[0m \u001b[43magent_executor\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43minvoke\u001b[49m\u001b[43m(\u001b[49m\u001b[43m{\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43minput\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m今天广州的天气\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m}\u001b[49m\u001b[43m)\u001b[49m\n",
      "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python310\\site-packages\\langchain\\chains\\base.py:163\u001b[0m, in \u001b[0;36mChain.invoke\u001b[1;34m(self, input, config, **kwargs)\u001b[0m\n\u001b[0;32m    161\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mBaseException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[0;32m    162\u001b[0m     run_manager\u001b[38;5;241m.\u001b[39mon_chain_error(e)\n\u001b[1;32m--> 163\u001b[0m     \u001b[38;5;28;01mraise\u001b[39;00m e\n\u001b[0;32m    164\u001b[0m run_manager\u001b[38;5;241m.\u001b[39mon_chain_end(outputs)\n\u001b[0;32m    166\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m include_run_info:\n",
      "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python310\\site-packages\\langchain\\chains\\base.py:153\u001b[0m, in \u001b[0;36mChain.invoke\u001b[1;34m(self, input, config, **kwargs)\u001b[0m\n\u001b[0;32m    150\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m    151\u001b[0m     \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_validate_inputs(inputs)\n\u001b[0;32m    152\u001b[0m     outputs \u001b[38;5;241m=\u001b[39m (\n\u001b[1;32m--> 153\u001b[0m         \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_call\u001b[49m\u001b[43m(\u001b[49m\u001b[43minputs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mrun_manager\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mrun_manager\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m    154\u001b[0m         \u001b[38;5;28;01mif\u001b[39;00m new_arg_supported\n\u001b[0;32m    155\u001b[0m         \u001b[38;5;28;01melse\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_call(inputs)\n\u001b[0;32m    156\u001b[0m     )\n\u001b[0;32m    158\u001b[0m     final_outputs: Dict[\u001b[38;5;28mstr\u001b[39m, Any] \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mprep_outputs(\n\u001b[0;32m    159\u001b[0m         inputs, outputs, return_only_outputs\n\u001b[0;32m    160\u001b[0m     )\n\u001b[0;32m    161\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mBaseException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m e:\n",
      "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python310\\site-packages\\langchain\\agents\\agent.py:1391\u001b[0m, in \u001b[0;36mAgentExecutor._call\u001b[1;34m(self, inputs, run_manager)\u001b[0m\n\u001b[0;32m   1389\u001b[0m \u001b[38;5;66;03m# We now enter the agent loop (until it returns something).\u001b[39;00m\n\u001b[0;32m   1390\u001b[0m \u001b[38;5;28;01mwhile\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_should_continue(iterations, time_elapsed):\n\u001b[1;32m-> 1391\u001b[0m     next_step_output \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_take_next_step\u001b[49m\u001b[43m(\u001b[49m\n\u001b[0;32m   1392\u001b[0m \u001b[43m        \u001b[49m\u001b[43mname_to_tool_map\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m   1393\u001b[0m \u001b[43m        \u001b[49m\u001b[43mcolor_mapping\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m   1394\u001b[0m \u001b[43m        \u001b[49m\u001b[43minputs\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m   1395\u001b[0m \u001b[43m        \u001b[49m\u001b[43mintermediate_steps\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m   1396\u001b[0m \u001b[43m        \u001b[49m\u001b[43mrun_manager\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mrun_manager\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m   1397\u001b[0m \u001b[43m    \u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m   1398\u001b[0m     \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(next_step_output, AgentFinish):\n\u001b[0;32m   1399\u001b[0m         \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_return(\n\u001b[0;32m   1400\u001b[0m             next_step_output, intermediate_steps, run_manager\u001b[38;5;241m=\u001b[39mrun_manager\n\u001b[0;32m   1401\u001b[0m         )\n",
      "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python310\\site-packages\\langchain\\agents\\agent.py:1097\u001b[0m, in \u001b[0;36mAgentExecutor._take_next_step\u001b[1;34m(self, name_to_tool_map, color_mapping, inputs, intermediate_steps, run_manager)\u001b[0m\n\u001b[0;32m   1088\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m_take_next_step\u001b[39m(\n\u001b[0;32m   1089\u001b[0m     \u001b[38;5;28mself\u001b[39m,\n\u001b[0;32m   1090\u001b[0m     name_to_tool_map: Dict[\u001b[38;5;28mstr\u001b[39m, BaseTool],\n\u001b[1;32m   (...)\u001b[0m\n\u001b[0;32m   1094\u001b[0m     run_manager: Optional[CallbackManagerForChainRun] \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m,\n\u001b[0;32m   1095\u001b[0m ) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m Union[AgentFinish, List[Tuple[AgentAction, \u001b[38;5;28mstr\u001b[39m]]]:\n\u001b[0;32m   1096\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_consume_next_step(\n\u001b[1;32m-> 1097\u001b[0m         [\n\u001b[0;32m   1098\u001b[0m             a\n\u001b[0;32m   1099\u001b[0m             \u001b[38;5;28;01mfor\u001b[39;00m a \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_iter_next_step(\n\u001b[0;32m   1100\u001b[0m                 name_to_tool_map,\n\u001b[0;32m   1101\u001b[0m                 color_mapping,\n\u001b[0;32m   1102\u001b[0m                 inputs,\n\u001b[0;32m   1103\u001b[0m                 intermediate_steps,\n\u001b[0;32m   1104\u001b[0m                 run_manager,\n\u001b[0;32m   1105\u001b[0m             )\n\u001b[0;32m   1106\u001b[0m         ]\n\u001b[0;32m   1107\u001b[0m     )\n",
      "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python310\\site-packages\\langchain\\agents\\agent.py:1097\u001b[0m, in \u001b[0;36m<listcomp>\u001b[1;34m(.0)\u001b[0m\n\u001b[0;32m   1088\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m_take_next_step\u001b[39m(\n\u001b[0;32m   1089\u001b[0m     \u001b[38;5;28mself\u001b[39m,\n\u001b[0;32m   1090\u001b[0m     name_to_tool_map: Dict[\u001b[38;5;28mstr\u001b[39m, BaseTool],\n\u001b[1;32m   (...)\u001b[0m\n\u001b[0;32m   1094\u001b[0m     run_manager: Optional[CallbackManagerForChainRun] \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m,\n\u001b[0;32m   1095\u001b[0m ) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m Union[AgentFinish, List[Tuple[AgentAction, \u001b[38;5;28mstr\u001b[39m]]]:\n\u001b[0;32m   1096\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_consume_next_step(\n\u001b[1;32m-> 1097\u001b[0m         [\n\u001b[0;32m   1098\u001b[0m             a\n\u001b[0;32m   1099\u001b[0m             \u001b[38;5;28;01mfor\u001b[39;00m a \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_iter_next_step(\n\u001b[0;32m   1100\u001b[0m                 name_to_tool_map,\n\u001b[0;32m   1101\u001b[0m                 color_mapping,\n\u001b[0;32m   1102\u001b[0m                 inputs,\n\u001b[0;32m   1103\u001b[0m                 intermediate_steps,\n\u001b[0;32m   1104\u001b[0m                 run_manager,\n\u001b[0;32m   1105\u001b[0m             )\n\u001b[0;32m   1106\u001b[0m         ]\n\u001b[0;32m   1107\u001b[0m     )\n",
      "File \u001b[1;32m~\\AppData\\Roaming\\Python\\Python310\\site-packages\\langchain\\agents\\agent.py:1136\u001b[0m, in \u001b[0;36mAgentExecutor._iter_next_step\u001b[1;34m(self, name_to_tool_map, color_mapping, inputs, intermediate_steps, run_manager)\u001b[0m\n\u001b[0;32m   1134\u001b[0m     raise_error \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mFalse\u001b[39;00m\n\u001b[0;32m   1135\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m raise_error:\n\u001b[1;32m-> 1136\u001b[0m     \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\n\u001b[0;32m   1137\u001b[0m         \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mAn output parsing error occurred. \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m   1138\u001b[0m         \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mIn order to pass this error back to the agent and have it try \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m   1139\u001b[0m         \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124magain, pass `handle_parsing_errors=True` to the AgentExecutor. \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m   1140\u001b[0m         \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mThis is the error: \u001b[39m\u001b[38;5;132;01m{\u001b[39;00m\u001b[38;5;28mstr\u001b[39m(e)\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m   1141\u001b[0m     )\n\u001b[0;32m   1142\u001b[0m text \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mstr\u001b[39m(e)\n\u001b[0;32m   1143\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mhandle_parsing_errors, \u001b[38;5;28mbool\u001b[39m):\n",
      "\u001b[1;31mValueError\u001b[0m: An output parsing error occurred. In order to pass this error back to the agent and have it try again, pass `handle_parsing_errors=True` to the AgentExecutor. This is the error: Could not parse LLM output: `I apologize for the confusion earlier. Here's the correct response to your question:`"
     ]
    }
   ],
   "source": [
    "agent_executor.invoke({\"input\": \"今天广州的天气\"})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "15ac3bfc",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
